Here's what the plugin does behind the scenes: Multi-Tenant Mode
- Performs compile time injection to add a "tenantId" column to all domain objects (multi-tenant mode)
- Adds a nullable constraint for the tenantId column (to avoid annoying validation failures)
- Intercepts and wraps all hibernate Criteria and Query that force filtering on tenantId so that:
- All GORM functions backed by a Criteria object always return records ONLY for the current tenant (createCriteria, countBy, exists, find, get, list, listOrderBy, withCriteria)
- All GORM functions backed by a Query object will inject a named parameter "tenantId" with the current tenantId if a named parameter already exists This is one way you can get around the tenant filtering if you need to.
- Listens to appropriate hibernate events to check for tenantId:
- onPreDelete - make sure the record you're deleting matches the current tenantId
- onLoad - make sure you the record you are loading matches the current tenantId
- onPreUpdate - make sure the record you are updating matches the current tenantId
- onPreInsert - set the current tenantId for the record being added.tenantId
Single-Tenant Mode
- Converts the "dataSource" bean into an AOP proxy that creates a new datasource for each tenant
Other
- For each spring bean marked as uniquePerTenant:
- Convert the spring bean definition to prototype (the spring container will need to be able to create a unique instance of the bean for each tenant)
- Replaces the original bean definition with a Spring AOP proxy definition. The proxy intercepts each method, locates the appropriate bean for the current tenant (or creates a new one if needed), and delegates the method call to that bean.
- Adds a request filter for all controllers that binds the value from session.tenantId to a threadLocal variable. All code processed during that thread's execution will apply only to that tenant.
- Adds a request filter for development mode only that sets the current session's tenantId by passing a request parameter, __tenantId.